import axios, { AxiosRequestConfig } from "axios";
import { message } from "antd";
import { getTokenAUTH } from "@/utils/service/auth";
import { defaultCustomOptions } from "@/utils/service/defaultConfig";

const pendingMap = new Map();

interface customOptionsType {
  repeatRequestCancel: boolean; //取消重复请求 默认true21e
  loading: boolean; //展示loading效果 默认false
  errorMessageShow: boolean; //展示错误信息 默认true
  codeMessageShow: boolean; //展示code不为0时信息 默认true
  succinctDataFormat: boolean; //简洁返回值 默认true
  carriersToken: boolean; //携带token 默认true
}

function instance(
  axiosConfig: AxiosRequestConfig,
  customOptions?: Partial<customOptionsType>
) {
  const service = axios.create(axiosConfig);
  // 自定义配置
  let custom_options = Object.assign(defaultCustomOptions, customOptions);

  // 请求拦截
  service.interceptors.request.use(
    (config) => {
      removePending(config);
      custom_options.repeatRequestCancel && addPending(config);
      // 自动携带token
      if (custom_options.carriersToken) {
        config.headers = Object.assign(
          { token: getTokenAUTH() },
          config.headers
        );
      }
      return config;
    },
    (error) => {
      return Promise.reject(error);
    }
  );

  // 响应拦截
  service.interceptors.response.use(
    (response) => {
      removePending(response.config);
      if (response.data.code === 501 || response.data.code === 502) {
        window.location.href = "/login";
      }
      //是否返回简洁模式
      return custom_options.succinctDataFormat ? response.data : response;
    },
    (error) => {
      error.config && removePending(error.config);
      custom_options.errorMessageShow && httpErrorStatusHandle(error); // 处理错误状态码
      return Promise.reject(error); // 错误继续返回给到具体页面
    }
  );
  return service;
}

export default instance;

/**
 * 处理异常
 * @param {*} error
 */
function httpErrorStatusHandle(error: any) {
  // 处理被取消的请求
  if (axios.isCancel(error))
    return console.error("请求的重复请求：" + error.message);
  let messageText = "";
  if (error && error.response) {
    const { status } = error.response;
    if (status === 404) {
      messageText = `请求地址未找到:${error.response.config.url}`;
    }
    const temp = "";
    if (temp) {
      messageText = temp;
    } else {
      messageText = "未知错误请联系管理员";
    }
  }
  if (error.message.includes("timeout")) messageText = "网络请求超时！";
  if (error.message.includes("Network"))
    messageText = window.navigator.onLine ? "服务端异常！" : "您断网了！";

  message.error(messageText);
}

/**
 * 储存每个请求的唯一cancel回调, 以此为标识
 * @param {*} config
 * 
 */
function addPending(config: AxiosRequestConfig) {
  const pendingKey = getPendingKey(config);
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken((cancel) => {
      if (!pendingMap.has(pendingKey)) {
        pendingMap.set(pendingKey, cancel);
      }
    });
}

/**
 * 删除重复的请求
 * @param {*} config
 */
function removePending(config: AxiosRequestConfig) {
  const pendingKey = getPendingKey(config);
  if (pendingMap.has(pendingKey)) {
    const cancelToken = pendingMap.get(pendingKey);
    cancelToken(pendingKey);
    pendingMap.delete(pendingKey);
  }
}

/**
 * 生成唯一的每个请求的唯一key
 * @param {*} config
 * @returns
 */
function getPendingKey(config: AxiosRequestConfig) {
  let { url, method, params, data } = config;
  if (typeof data === "string") data = JSON.parse(data); // response里面返回的config.data是个字符串对象
  return [url, method, JSON.stringify(params), JSON.stringify(data)].join("&");
}
